/* eslint-disable @iceworks/best-practices/recommend-polyfill */
import { useEffect, memo, useState } from 'react';
import NoVideo from './novideo.png';

// 缓存器
const VideoCache = {
  mapper: {},
  canvasPool: [] as HTMLCanvasElement[],
  poolSize: 5, // 资源池大小
  requestQueue: [] as Array<{ resolve: (canvas: HTMLCanvasElement) => void }>,

  initCanvasPool() {
    for (let i = 0; i < this.poolSize; i++) {
      const canvas = document.createElement('canvas');
      this.canvasPool.push(canvas);
    }
  },

  async getCanvasFromPool(): Promise<HTMLCanvasElement> {
    if (this.canvasPool.length > 0) {
      return this.canvasPool.pop()!;
    } else {
      // 如果资源池为空，将请求加入队列
      return new Promise((resolve) => {
        this.requestQueue.push({ resolve });
      });
    }
  },

  releaseCanvasToPool(canvas: HTMLCanvasElement) {
    if (this.requestQueue.length > 0) {
      // 如果有等待的请求，直接分配canvas
      const { resolve } = this.requestQueue.shift()!;
      resolve(canvas);
    } else if (this.canvasPool.length < this.poolSize) {
      // 否则将canvas放回资源池
      this.canvasPool.push(canvas);
    }
  },

  async getThumbnail(videoUrl: string): Promise<string> {
    const cache = await caches.open('video-thumbnails');

    const cachedResponse = await cache.match(videoUrl);
    if (cachedResponse) {
      return await cachedResponse.text();
    }

    // 如果没有缓存
    if (!this.mapper[videoUrl]) {
      this.mapper[videoUrl] = this.getCanvasFromPool()
        .then((canvas) => {
          return new Promise((resolve, reject) => {
            const context = canvas.getContext('2d');
            if (!context) return;

            const video = document.createElement('video');

            // 加载video
            video.src = videoUrl;
            video.crossOrigin = 'anonymous';
            // 定义事件处理函数并保存引用
            const handleLoadedData = () => {
              video.currentTime = Math.floor(video.duration * 0.25); // 设置视频的时间点
              // video.currentTime = 0;
            };
            const handleSeeked = async () => {
              canvas.width = video.videoWidth;
              canvas.height = video.videoHeight;
              context.drawImage(video, 0, 0, canvas.width, canvas.height);

              const url = canvas.toDataURL('image/png');

              // cache 存放1小时
              const response = new Response(url, {
                headers: { 'cache-control': 'max-age: 3600' },
              });
              await cache.put(videoUrl, response);

              // 释放canvas回资源池
              this.releaseCanvasToPool(canvas);
              resolve(url);
            };
            const handleError = () => {
              // 释放canvas回资源池
              this.releaseCanvasToPool(canvas);
              reject();
            };

            // 添加事件监听器
            video.addEventListener('loadeddata', handleLoadedData);
            video.addEventListener('seeked', handleSeeked);
            video.addEventListener('error', handleError);
          });
        })
        // 释放资源
        .finally(() => {
          delete this.mapper[videoUrl];
        });
    }
    return this.mapper[videoUrl];
  },
};

// 初始化canvas资源池
VideoCache.initCanvasPool();

const VideoThumbnail = (props: { videoUrl: string; thumbnail?: string } & React.HTMLAttributes<HTMLImageElement>) => {
  const { videoUrl, thumbnail, className, onClick } = props;

  const [imgUrl, setImgUrl] = useState<string>();

  useEffect(() => {
    // 如果存在后台缩略图地址
    if (thumbnail) {
      setImgUrl(thumbnail);
      return;
    }

    // 如果不存在视频
    if (!videoUrl) {
      setImgUrl(NoVideo);
      return;
    }

    VideoCache.getThumbnail(videoUrl)
      .then((url) => setImgUrl(url))
      .catch(() => setImgUrl(NoVideo));
  }, [videoUrl, thumbnail]);

  return <img src={imgUrl} className={className} onClick={onClick} />;
};

export default memo(VideoThumbnail);
